﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Text;
using Ue.Infrastructure;
using Ue.Infrastructure.DomainBase;
using Ue.Infrastructure.RepositoryFramework.Repository;
using Ue.Qcdz.Domain;
using Ue.Qcdz.Domain.Membership;
using Ue.Framework.Data;
using Ue.Qcdz.Domain.Roles;
using Ue.Qcdz.UI.Controls;


namespace Ue.Qcdz.Repositories.Membership
{
    public class UserRepository : SqlServerRepository<User>, IUserRepository
    {

        public UserRepository()
            : this(null) { }

        public UserRepository(IUnitOfWork uniteOfWork)
            : base(uniteOfWork)
        {

        }

        protected override string GetDataTableName()
        {
            return "Users";
        }

        protected override string GetKeyFieldName()
        {
            return UserFactory.FieldNames.EntityKey;
        }

        #region 原注册方法.注销
        //protected override string[] GetBaseInsertFields()
        //{
        //    return new string[]{
        //        UserFactory.FieldNames.EntityKey,
        //        UserFactory.FieldNames.UserName,
        //        UserFactory.FieldNames.Password,
        //        UserFactory.FieldNames.PasswordQuestion,
        //        UserFactory.FieldNames.PasswordOtherQuestion,
        //        UserFactory.FieldNames.PasswordAnswer,
        //        UserFactory.FieldNames.LastLoginDate,
        //        UserFactory.FieldNames.State

        //    };
        //} 
        #endregion
        protected override string[] GetBaseInsertFields()
        {
            return new string[]{
                UserFactory.FieldNames.EntityKey,
                UserFactory.FieldNames.UserName,
                UserFactory.FieldNames.Password,
                UserFactory.FieldNames.LastLoginDate,
                UserFactory.FieldNames.State
                
            };
        }
        protected override string[] GetBaseUpdateFields()
        {
            return new string[]{
                UserFactory.FieldNames.UserName,
                UserFactory.FieldNames.Password,
                UserFactory.FieldNames.LastLoginDate,
                UserFactory.FieldNames.State
            };
        }

        protected override IDataParameter[] BuildParameters(User entity)
        {
            return new IDataParameter[]
                       {
                           this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.EntityKey, entity.Key),
                           this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.UserName, entity.UserName),
                           this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.Password, entity.Password),
                           this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.LastLoginDate,
                                                                entity.LastLoginDate),
                           this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.State, (int) entity.State)
                           
            };
        }

        protected override string GetOrderBy()
        {
            return "CreateOn Desc";
        }

        protected override IWhereClause BuildWhereClauseBy(IDataQuery dataQuery)
        {

            UserList userList = dataQuery as UserList;
            if (userList != null)
            {
                return new UserWhereClause(userList);
            }
            return null;
        }

        protected override IDictionary<string, SqlServerRepositoryBase<User>.ChildDataHandler> GetBuildEntityChildCallbacks()
        {
            var callBacks = new Dictionary<string, SqlServerRepository<User>.ChildDataHandler>();

            callBacks.Add(UserFactory.FieldNames.EntityKey, delegate(User user, object objectValue)
            {
                var query = "select * from UserProfile where UserId=@UserId ";

                IDataReader reader = this.RepositoryDriver.ExecuteReader(
                    this.RepositoryDriver.BuildCommand(
                        query,
                        this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.UserInProfileKey, objectValue)));

                if (reader.Read())
                {
                    user.Profile.Name = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.Name);
                    user.Profile.MobilePhone = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.MobilePhone);
                    user.Profile.Sex = reader.Get<int>(UserFactory.FieldNames.ProfileFieldNames.Sex);
                    user.Profile.Fax = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.Fax);
                    user.Profile.PostalCode = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.PostalCode);
                    user.Profile.Telephone = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.Telephone);
                    user.Profile.Street = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.Street);
                    user.Profile.Company = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.Company);
                    user.Profile.CompanyAddress =
                        reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.CompanyAddress);
                    user.Profile.QQnumber = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.QQnumber);
                    user.Profile.UserAddress = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.UserAddress);

                    user.Profile.Birthday = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.Birthday);
                    user.Profile.Email = reader.Get<string>(UserFactory.FieldNames.ProfileFieldNames.Email);
                }
                IRoleRepository roleRepository =
                   Ue.Infrastructure.RepositoryFramework.RepositoryFactory.GetRepository<IRoleRepository, Role>();
                IList<Role> roleList = roleRepository.GetRoleList(user);
                user.ChangeRoleList((List<Role>)roleList);

            });

            return callBacks;
        }


        protected override void PersistUpdatedItem(User item)
        {
            base.PersistUpdatedItem(item);
            var query =
                "UPDATE UserProfile SET Name=@Name,Sex=@Sex,Birthday=@Birthday,MobilePhone=@MobilePhone,Telephone=@Telephone,Email=@Email,UserAddress=@UserAddress,PostalCode=@PostalCode,QQnumber=@QQnumber WHERE UserId=@UserId";
            RepositoryDriver.ExecuteNonQuery(
                this.RepositoryDriver.BuildCommand(
                    query,
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.UserInProfileKey,
                                                         item.Key),
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.Name,
                                                         item.Profile.Name),
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.Sex, (int)item.Profile.Sex),


                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.Birthday, item.Profile.Birthday),

                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.MobilePhone,
                                                         item.Profile.MobilePhone),
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.Telephone,
                                                         item.Profile.Telephone),
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.Email, item.Profile.Email),

                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.UserAddress, item.Profile.UserAddress),

                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.PostalCode, item.Profile.PostalCode),

                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.QQnumber, item.Profile.QQnumber)
                    ));

        }
        protected override void PersistDeletedItem(User item)
        {
            Delete(item);
            base.PersistDeletedItem(item);
        }
        protected override void PersistNewItem(User item)
        {
            base.PersistNewItem(item);

            var query = "INSERT INTO UserProfile(UserId,Company,CompanyAddress,MobilePhone,Telephone,Email)VALUES(@UserId,@Company,@CompanyAddress,@MobilePhone,@Telephone,@Email);";
            RepositoryDriver.ExecuteNonQuery(
                 this.RepositoryDriver.BuildCommand(
                    query,
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.UserInProfileKey, item.Key),
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.Company, item.Profile.Company),
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.CompanyAddress, item.Profile.CompanyAddress),
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.MobilePhone, item.Profile.MobilePhone),
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.Telephone, item.Profile.Telephone),
                    this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.ProfileFieldNames.Email, item.UserName)
                    ));

        }
        private void Delete(User user)
        {
            var builder = new StringBuilder();
            builder.Append("delete from ShopNews where shopId =(select id from shop where userId=@UserId);");
            builder.Append("delete from ShopSinglePage where shopId =(select id from shop where userId=@UserId);");
            builder.Append("delete from Shop where UserId=@UserId;");
            builder.Append("delete from UserProfile where UserId=@UserId;");
            builder.Append("delete from UserInRoles where UserId=@UserId;");



            RepositoryDriver.ExecuteNonQuery(
                 this.RepositoryDriver.BuildCommand(
                    builder.ToString(),
                    this.RepositoryDriver.BuildParameter("@UserId", user.Key)
                    ));
        }

        #region IUserRepository 成员
        public User FindBy(string userName)
        {
            string sql = "SELECT * FROM Users WHERE UserName=@UserName";
            var parameter = new IDataParameter[]
                                             {
                                                 this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.UserName,
                                                                                      userName)
                                                               
            };
            return BuildEntityFromSql(sql, parameter);
        }

        public void ChangeStatus(EntityState state, string userId)
        {
            var query = "UPDATE Users SET State=@State WHERE Id=@Id";
            RepositoryDriver.ExecuteNonQuery(
                       this.RepositoryDriver.BuildCommand(
                           query,
                           this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.State,
                                                                state),
                           this.RepositoryDriver.BuildParameter(UserFactory.FieldNames.EntityKey, userId)
                           ));
        }

        public IList<User> GetUsersInRole(string roleName)
        {
            const string query =
                "SELECT * FROM Users WHERE Id IN(SELECT UserId FROM Roles Inner join UserInRoles ON Roles.Id=UserInRoles.RoleId WHERE Name=@Name)";
            return this.BuildEntitiesFromSql(query, this.RepositoryDriver.BuildParameter("@Name", roleName));

        }

        #endregion


        public class UserWhereClause : IWhereClause
        {
            private UserList userList;

            public UserWhereClause(UserList userList)
            {
                this.userList = userList;
            }

            public string Clause
            {

                get
                {
                    var clause = "UserName LIKE '%'+@UserName+'%' AND State LIKE '%'+@State+'%'";
                    return clause;
                }

            }

            public IDataParameter[] Parameters
            {

                get
                {
                    string strUserName = userList.SearchKey;
                    if (string.IsNullOrEmpty(strUserName)) strUserName = "";
                    string strStatus = userList.State;
                    if (string.IsNullOrEmpty(strStatus)) strStatus = "";

                    var Parameters = new IDataParameter[]
                                         {
                                             SqlServerDriver.Instance.BuildParameter(UserFactory.FieldNames.UserName,
                                                                                     strUserName),
                                             SqlServerDriver.Instance.BuildParameter(UserFactory.FieldNames.State,
                                                                                     strStatus)
                                     };
                    return Parameters;
                }

            }
        }
    }
}
